package emby.expr;

import emby.EmbyRuntime;
import emby.err.SyntaxError;
import emby.lang.BuiltInOperators;
import emby.lang.EmbyFunction;
import emby.lang.Scope;
import emby.util.Print;
import emby.writer.IEmbyCodifier;

/**
 * Represents an built-in operator call.
 * @author Justin
 *
 */
public class OperatorCall extends Call{


	private static final long serialVersionUID = -7747423154264423703L;
	EmbyFunction op;
	Expression[] args;
	public OperatorCall(EmbyFunction operator, Expression... args){
		super(null,(Expression)null);
		op=operator;
		this.args = args;
	}
	public OperatorCall(String op, Expression...args){
		this(toFunction(op),args);
	}

	public static EmbyFunction toFunction(String op){
		if(op.equals("+")){
			return BuiltInOperators.add;
		}
		if(op.equals("-")){
			return BuiltInOperators.sub;
		}
		if(op.equals("*")){
			return BuiltInOperators.mul;
		}
		if(op.equals("/")){
			return BuiltInOperators.div;
		}
		if(op.equals("%")){
			return BuiltInOperators.mod;
		}
		if(op.equals("==")){
			return BuiltInOperators.eqeq;
		}
		if(op.equals("!=")){
			return BuiltInOperators.noteq;
		}
		if(op.equals(">")){
			return BuiltInOperators.greater;
		}
		if(op.equals("<")){
			return BuiltInOperators.less;
		}
		if(op.equals(">=")){
			return BuiltInOperators.greatereq;
		}
		if(op.equals("<=")){
			return BuiltInOperators.lesseq;
		}
		if(op.equals("&&")){
			return BuiltInOperators.and;
		}
		if(op.equals("||")){
			return BuiltInOperators.or;
		}
		if(op.equals("!")){
			return BuiltInOperators.not;
		}
		if(op.equals("is")){
			return BuiltInOperators.is;
		}
		if(op.equals("^")){
			return BuiltInOperators.carrot;
		}
		if(op.equals(".")){
			new InternalError("Dot Var was parsed incorrectly as an infix expression!");
		}
		if( op.endsWith("=")){ //handling for compound assignment, like += or *=
			return toFunction( op.substring(0, op.length()-1));
		}
		throw new SyntaxError(-1,"Operator not found: "+op);
		//return null;
	}

	public Object eval(Scope s){
		if(EmbyRuntime.echo){
			Print.println("Calling built-in-operator ",op," on ", args," (",args.length," args)");
			Print.tab();
		}

		Object[] evaluated_args = new Object[args.length];
		for(int i = 0; i<args.length;i++){
			evaluated_args[i] = args[i].eval(s);
		}
		Object result = op.execute(getLine(),s,evaluated_args);
		if(EmbyRuntime.echo){
			emby.util.Print.println("Result of call: "+result);
			Print.untab();
		}
		return result;
	}
	public String toString(){
		return "{Infix call: "+op.toString()+"}";
	}
	
	public void codify(IEmbyCodifier ec){
		ec.opcall(op, args);
	}
}
